//
// Created by wxd on 2025/7/28.
//
#pragma once

#include <unordered_map>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>

#include "ICameraControl.h"
#include "../BaseCamera.h"

enum class ControlEvent {
    LEFTMOUSEDOWN, RIGHTMOUSEDOWN, MIDDLEMOUSEDOWN, LEFTMOUSEUP, RIGHTMOUSEUP, MIDDLEMOUSEUP, MOUSEMOVE, SCROLL,
    KEYBOARD
};

// 支持欧拉角和四元数
enum class RotateType {
    EULER,
    QUAT
};

enum CameraMoveDirection {
    LEFT, RIGHT, UP, DOWN, NONE
};

struct MouseStatus {
    bool isLeftMouseDown;
    bool isRightMouseDown;
    bool isMiddleMouseDown;

    float curMousePosX;
    float curMousePosY;
    float lastMousePosX;
    float lastMousePosY;
    float downMousePosX;
    float downMousePosY;

    MouseStatus() : isLeftMouseDown(false), isRightMouseDown(false), isMiddleMouseDown(false),
                    curMousePosX(0.f), curMousePosY(0.f), downMousePosX(0.f), downMousePosY(0.f),
                    lastMousePosX(0.f), lastMousePosY(0.f) {}
    MouseStatus(const MouseStatus&) = default;
    MouseStatus& operator=(const MouseStatus&) = default;

    void toString() const {
        std::ostringstream oss;
        oss << "[MouseStatus]" << " " << "leftDown: " << isLeftMouseDown << "; " << "middleDown"
        << isMiddleMouseDown << "; " << "rightDown: " << isRightMouseDown << "; " << "curX: " << curMousePosX
        << "; " << "curY: " << curMousePosY << "; downX: " << downMousePosX << "; downY: " << downMousePosY
        << "; lastX: " << lastMousePosX << "; lastY: " << lastMousePosY;

        std::cout << oss.str() << "\n";
    }
};


class BaseCameraControl : public ICameraControl {
public:


    BaseCameraControl() : m_Camera(nullptr), m_RotateType(RotateType::EULER),
        m_LastVerticalDirection(NONE), m_LastHorizonDirection(NONE), isVerticalReverse(false), isHorizonRevers(false) {}
    ~BaseCameraControl() override;

    static std::string ControlEventToString(ControlEvent event);

    void onCursor(float xpos, float ypos) override;
    void onKeyBoard(int key, int action, int mods) override;
    void onMouse(int button, int action, double xpos, double ypos) override;
    void onScroll(double yoffset) override;
    void update() override;

    void forEachControlEvent() const;
    void forEachKeyEvent() const;
    void setEnableControlInfo(bool enable);
    void setCamera(BaseCamera* camera);
    void setRotateType(RotateType type);

protected:
    BaseCamera* m_Camera;

    MouseStatus m_MouseStatus;

    std::unordered_map<int, bool> m_KeyBoardMap;
    std::vector<ControlEvent> m_EventList;

    RotateType m_RotateType;

    CameraMoveDirection m_LastVerticalDirection;        // 记录上一次相机移动竖直方向
    CameraMoveDirection m_LastHorizonDirection;         // 记录上一次相机移动水平方向

    bool isVerticalReverse;
    bool isHorizonRevers;

    static const glm::vec3 worldUp;
private:
    bool m_EnableOutputControlInfo { false };
};